<?php

namespace Ku;

final class Fuzzy {
    
    protected static $_instance = null;
    protected $_needed = null;
    protected $_length = 0;
    protected $_fillChar = '*';
    protected $_encoding = 'UTF-8';

    private function __construct() {}
    private function __sleep() {}
    private function __clone() {}
    
    /**
     * @return \Lib\Fuzzy
     */
    public static function init($mixed, $fillChar = null) {
        if (!self::$_instance instanceof self) {
            self::$_instance = new self();
        }
        
        $that = self::$_instance;
        
        $that->_needed   = (string)(mb_convert_encoding($mixed, $that->_encoding, mb_detect_order()));
        $that->_length   = mb_strlen($that->_needed, $that->_encoding);
        $that->_fillChar = empty($fillChar) ? '*' : $fillChar;
        
        return $that;
    }
    
    /**
     * 模糊手机号
     * 
     * @param int $offset 模糊的字符偏移位置
     * @return string
     */
    public function phoneNumber($offset = 3) {
        return $this->general($this->_length - $offset*2, $offset, 0);
    }
    
    /**
     * 银行卡号模糊
     * 
     * @param int $rflen 不进行模糊的字符长度(从末尾起算)
     * @return string
     */
    public function bankCard($rflen = 4) {
        $card = $this->general($this->_length - $rflen, 0);
        
        return implode(' ', str_split($card, 4));
    }

    /**
     * 模糊ID(身份证)
     * 
     * @param int $offset 模糊的字符偏移位置
     * @return string
     */
    public function ID($offset = 1) {
        return $this->general($this->_length - $offset*2, $offset, 0);
    }
    
    /**
     * 模糊Email
     * 
     * @param int $offset 模糊的字符偏移位置
     * @param int $fixedLen  > 0时模糊的字符以$fixedLen长度填充
     * @return string
     */
    public function email($offset = 3, $fixedLen = 0) {
        $atIndex = strpos($this->_needed, '@');
        $flen = ($atIndex%2 === 0 ? $atIndex/2 : ++$atIndex/2);

        if($offset >= ($atIndex - 1) ) {
            $offset = $flen - 1;
        }
        
        return $this->general($flen, $offset, $fixedLen);
    }
    
    /**
     * 中文姓名模糊
     * 
     * @param int $offset 模糊的字符偏移位置
     * @param int $fixedLen  > 0时模糊的字符以$fixedLen长度填充
     * @return string
     */
    public function fullName($offset = 0, $fixedLen = 0) {
        $slen = $this->_length;
        $flen = (int)($slen/2);
        
        return $this->general($flen, $offset, $fixedLen);
    }

    /**
     * 一般模糊处理
     * 
     * @param int $flen  模糊的字符长度
     * @param int $offset 模糊的字符偏移位置
     * @param int $fixedLen  > 0时模糊的字符以$fixedLen长度填充
     * @return string
     * @throws \Exception
     */
    public function general($flen = 3, $offset = 0, $fixedLen = 0) {
        $nval = $this->_needed;
        $slen = $this->_length;
        $nlen = ($flen > 0 && $flen < $slen) ? $flen : ($slen > $offset ? $slen - $offset : 0);
        $klen = $offset + $nlen;
        $rval = '';

        if($offset > 0) {
            $rval .= mb_substr($nval, 0, $offset, $this->_encoding);
        }

        if($nlen > 0) {
            $rval .= str_repeat($this->_fillChar, $fixedLen ?: $nlen);
        }
        
        if($klen < $slen) {
            $rval .= mb_substr($nval, $klen, $slen - $klen, $this->_encoding);
        }
        
        return $rval;
    }
}